/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.seari.modbusServer;

import com.ghgande.j2mod.modbus.ModbusCoupler;
import com.ghgande.j2mod.modbus.net.AbstractModbusListener;
import com.ghgande.j2mod.modbus.procimg.File;
import com.ghgande.j2mod.modbus.procimg.Record;
import com.ghgande.j2mod.modbus.procimg.SimpleDigitalIn;
import com.ghgande.j2mod.modbus.procimg.SimpleDigitalOut;
import com.ghgande.j2mod.modbus.procimg.SimpleInputRegister;
import com.ghgande.j2mod.modbus.procimg.SimpleProcessImage;
import com.ghgande.j2mod.modbus.procimg.SimpleRegister;
import com.seari.modbusServer.bean.VirtualModbus;
import com.seari.modbusServer.MainController;
import com.seari.modbusServer.utils.MiscTools;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Rainbow
 */
public class ModbusSlaveServer implements Runnable
{

    @Override
    public void run()
    {
        String[] args = new String[1];
        Properties config = MainController.config;
        if (null == config)
        {
            try
            {
                config = MiscTools.loadConfig("config.cfg");
            } catch (Exception ex)
            {
                Logger.getLogger(ModbusSlaveServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        String ipAndPort = config.getProperty("virtual_modbus_ip_port");
        args[0] = "tcp:" + ipAndPort;
        AbstractModbusListener listener = null;
        SimpleProcessImage spi;

        try
        {
            System.out.println("j2mod Modbus Slave (Server) v0.97");

            // Create the process image for this test.
            spi = new SimpleProcessImage(1);

            spi.addDigitalOut(new SimpleDigitalOut(true));
            spi.addDigitalOut(new SimpleDigitalOut(true));

            spi.addDigitalIn(new SimpleDigitalIn(false));
            spi.addDigitalIn(new SimpleDigitalIn(true));
            spi.addDigitalIn(new SimpleDigitalIn(false));
            spi.addDigitalIn(new SimpleDigitalIn(true));

            spi.addFile(new File(0, 10).setRecord(0, new Record(0, 10)).setRecord(1, new Record(1, 10)).setRecord(2, new Record(2, 10)).setRecord(3, new Record(3, 10)).setRecord(4, new Record(4, 10)).setRecord(5, new Record(5, 10)).setRecord(6, new Record(6, 10)).setRecord(7, new Record(7, 10)).setRecord(8, new Record(8, 10)).setRecord(9, new Record(9, 10)));

            spi.addFile(new File(1, 20).setRecord(0, new Record(0, 10)).setRecord(1, new Record(1, 20)).setRecord(2, new Record(2, 20)).setRecord(3, new Record(3, 20)).setRecord(4, new Record(4, 20)).setRecord(5, new Record(5, 20)).setRecord(6, new Record(6, 20)).setRecord(7, new Record(7, 20)).setRecord(8, new Record(8, 20)).setRecord(9, new Record(9, 20)).setRecord(10, new Record(10, 10)).setRecord(11, new Record(11, 20)).setRecord(12, new Record(12, 20)).setRecord(13, new Record(13, 20)).setRecord(14, new Record(14, 20)).setRecord(15, new Record(15, 20)).setRecord(16, new Record(16, 20)).setRecord(17, new Record(17, 20)).setRecord(18, new Record(18, 20)).setRecord(19, new Record(19, 20))
            );

            // allow checking LSB/MSB order
            int startPos = VirtualModbus.posList.get(0);
            int endPos = VirtualModbus.posList.get(VirtualModbus.posList.size() - 1);
            for (int i = startPos; i <= endPos; i++)
            {
                spi.addRegister(i, new SimpleRegister(i));
                //System.out.println("count i:"+i);
            }
            //spi.addRegister(10,new SimpleRegister(1));
            spi.addInputRegister(new SimpleInputRegister(45));
            // 2. create the coupler holding the image
            ModbusCoupler.getReference().setProcessImage(spi);
            ModbusCoupler.getReference().setMaster(false);
//            ModbusSlave slave = ModbusSlaveFactory.createTCPSlave(502, 3);
//            slave.addProcessImage(spi.getUnitID(), spi);
            // 3. create a listener with 3 threads in pool
            System.out.println("Creating");

            listener = SEmodbusListenerFactory.createModbusListener(args[0],5);

            System.out.println("Listening");

            while (listener.isListening())
            {
                try
                {
                    Thread.sleep(1000L);
                } catch (InterruptedException x)
                {
                    listener.stop();
                    break;
                }
            }
            System.out.println("Done");
            System.out.println("started at port"+ipAndPort);
        } catch (Exception x)
        {
            System.out.printf(x.toString());
            if (listener != null)
            {
                listener.stop();
            }
        }
    }
}
